package com.codesgood.views;

import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.Text;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.app.Context;

import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.List;

/**
 * 自定义对齐text组件
 */
public class JustifiedTextView extends Text implements Component.DrawTask {
    private static final String HAIR_SPACE = "\u200A";
    private static final String NORMAL_SPACE = " ";
    private int viewWidth;
    private List<String> sentences = new ArrayList<>();
    private List<String> currentSentence = new ArrayList<>();
    private List<String> sentenceWithSpaces = new ArrayList<>();
    private String justifiedText = "";
    private SecureRandom random = new SecureRandom();

    /**
     * @param context 上下文
     */
    public JustifiedTextView(Context context) {
        this(context,null);
    }

    /**
     * @param context 上下文
     * @param attrSet 资源
     */
    public JustifiedTextView(Context context, AttrSet attrSet) {
        this(context, attrSet,null);
    }

    /**
     * @param context   上下文
     * @param attrSet   资源
     * @param styleName 样式
     */
    public JustifiedTextView(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
        addDrawTask(this);
    }

    @Override
    public void onDraw(Component component, Canvas canvas) {
        if (!justifiedText.equals(getText().toString())) {
            ComponentContainer.LayoutConfig params = getLayoutConfig();
            String text = getText().toString();
            viewWidth = getWidth() - (getPaddingLeft() + getPaddingRight());
            if (params.width != ComponentContainer.LayoutConfig.MATCH_CONTENT && viewWidth > 0 && !text.isEmpty()) {
                justifiedText = getJustifiedText(text);
                if (!justifiedText.isEmpty()) {
                    setText(justifiedText);
                    sentences.clear();
                    currentSentence.clear();
                }
            }
        }
    }

    private String getJustifiedText(String text) {
        String[] words = text.split(NORMAL_SPACE);
        for (String word : words) {
            boolean containsNewLine = (StringUtil.isContainsN(word) || StringUtil.isContainsR(word));
            if (fitsInSentence(word, currentSentence, true)) {
                addWord(word, containsNewLine);
            } else {
                sentences.add(fillSentenceWithSpaces(currentSentence));
                currentSentence.clear();
                addWord(word, containsNewLine);
            }
        }
        if (currentSentence.size() > 0) {
            sentences.add(getSentenceFromList(currentSentence, true));
        }
        return getSentenceFromList(sentences, false);
    }

    private void addWord(String word, boolean containsNewLine) {
        currentSentence.add(word);
        if (containsNewLine) {
            sentences.add(getSentenceFromListCheckingNewLines(currentSentence));
            currentSentence.clear();
        }
    }

    private String getSentenceFromList(List<String> strings, boolean addSpaces) {
        StringBuilder stringBuilder = new StringBuilder();
        for (String string : strings) {
            stringBuilder.append(string);
            if (addSpaces) {
                stringBuilder.append(NORMAL_SPACE);
            }
        }
        return stringBuilder.toString();
    }

    private String getSentenceFromListCheckingNewLines(List<String> strings) {
        StringBuilder stringBuilder = new StringBuilder();

        for (String string : strings) {
            stringBuilder.append(string);
            if (!StringUtil.isContainsN(string) && !StringUtil.isContainsR(string)) {
                stringBuilder.append(NORMAL_SPACE);
            }
        }

        return stringBuilder.toString();
    }

    private String fillSentenceWithSpaces(List<String> sentence) {
        sentenceWithSpaces.clear();
        if (sentence.size() > 1) {
            for (String word : sentence) {
                sentenceWithSpaces.add(word);
                sentenceWithSpaces.add(NORMAL_SPACE);
            }
            while (fitsInSentence(HAIR_SPACE, sentenceWithSpaces, false)) {
                sentenceWithSpaces.add(getRandomNumber(sentenceWithSpaces.size() - 2), HAIR_SPACE);
            }
        }
        return getSentenceFromList(sentenceWithSpaces, false);
    }

    private boolean fitsInSentence(String word, List<String> sentence, boolean addSpaces) {
        String stringSentence = getSentenceFromList(sentence, addSpaces);
        stringSentence += word;
        Paint paint = new Paint();
        paint.setTextSize(getTextSize());
        float sentenceWidth = paint.measureText(stringSentence);
        return sentenceWidth < viewWidth;
    }

    private int getRandomNumber(int max) {
        return random.nextInt(max) + 1;
    }
}
